{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "d1822a7d-5698-4f4d-92ec-7f712fac9d49",
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "import re\n",
    "import jieba\n",
    "from tqdm import tqdm\n",
    "import torch\n",
    "from opencc import OpenCC"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "6831f6f9-c45e-4e48-82e9-e8f9b02d207f",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "device(type='cuda')"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 检查是否有可用的 GPU\n",
    "device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n",
    "device"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "1816afb0-2565-4fbd-917d-54c4b391fc9e",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "数据数量508110\n",
      "                                                  content  stars  label\n",
      "307506  海报很好看，吸引我去看，有一点特色，但是故事比较牵强，没有伏笔，最后世纪大战用的是动画……e...      2      0\n",
      "16225   看到有两个加菲猫，过着两种不同的生活，我很自然地想到王子与贫儿，明摆着的情节，不过还是被这只...      4      1\n",
      "173423           也许历史就像海帕西娅的椭圆的轨迹，你以为已经渐行渐远，转了一圈却又回到了最近点。      5      1\n",
      "273991  看来我是欣赏不了这样的演员表演了，大家扯着嗓子本色的喊台词，加上丑到cry的妖怪造型，加上中...      2      0\n",
      "114262                                             中字已收录。      5      1\n"
     ]
    }
   ],
   "source": [
    "# 读取数据集\n",
    "data_path = '../datasets/chinese_movie_reviews/chinese_movie_reviews_datasets.jsonl'\n",
    "df = pd.read_json(data_path, orient='records', lines=True)\n",
    "print(f'数据数量{len(df)}')\n",
    "print(df.sample(5))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "97bd708c-5e3a-487b-a8b9-026f91c9b685",
   "metadata": {},
   "source": [
    "## 数据预处理\n",
    "\n",
    "1. 分词\n",
    "2. 训练Word2Vec：生成一个包含语料库中的每个词的向量空间"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "6da13e00-6a47-453a-8faf-fd551b5c8ac4",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Building prefix dict from the default dictionary ...\n",
      "Loading model from cache C:\\Users\\PC\\AppData\\Local\\Temp\\jieba.cache\n",
      "Loading model cost 0.295 seconds.\n",
      "Prefix dict has been built successfully.\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "最大文本长度：625\n",
      "平均文本长度：21.04\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>content</th>\n",
       "      <th>stars</th>\n",
       "      <th>label</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>381987</th>\n",
       "      <td>黄河 民歌 风土 线 人物 个体 经历 线 好像 没 确定 重点 或者说 有些 疏离 看 会...</td>\n",
       "      <td>3</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>263723</th>\n",
       "      <td>无悔 不悲 感恩 幸福 体验</td>\n",
       "      <td>3</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>265531</th>\n",
       "      <td>好久没 看到 难看 片子</td>\n",
       "      <td>2</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>333061</th>\n",
       "      <td>意境 差太多</td>\n",
       "      <td>3</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>81841</th>\n",
       "      <td>拍到 还 好看 第一部 讲 友情 第二部 讲 玩具 意义 第三部 讲 成长 第四部 讲 爱情...</td>\n",
       "      <td>4</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                                                  content  stars  label\n",
       "381987  黄河 民歌 风土 线 人物 个体 经历 线 好像 没 确定 重点 或者说 有些 疏离 看 会...      3      0\n",
       "263723                                     无悔 不悲 感恩 幸福 体验      3      0\n",
       "265531                                       好久没 看到 难看 片子      2      0\n",
       "333061                                             意境 差太多      3      0\n",
       "81841   拍到 还 好看 第一部 讲 友情 第二部 讲 玩具 意义 第三部 讲 成长 第四部 讲 爱情...      4      1"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 初始化 OpenCC 转换器（繁转简）\n",
    "cc = OpenCC('t2s')  # t2s 表示繁体转简体\n",
    "\n",
    "# 读取停用词表\n",
    "with open('../datasets/chinese_movie_reviews/stopwords.txt', 'r', encoding='utf-8') as f:\n",
    "    stopwords = [line.strip() for line in f.readlines()]\n",
    "\n",
    "# 繁体字转简体字\n",
    "def traditional_to_simplified(text):\n",
    "    return cc.convert(text)\n",
    "\n",
    "# 移除数字\n",
    "def remove_digit(text):\n",
    "     return re.sub(r'\\d+', '', text)\n",
    "\n",
    "# 分词处理\n",
    "def tokenize(text):\n",
    "    return \" \".join(jieba.cut(text))\n",
    "\n",
    "def remove_stopwords(text):\n",
    "    return \" \".join([word for word in text.split() if word not in stopwords])\n",
    "\n",
    "# 应用预处理\n",
    "def process_row(text):\n",
    "    text = remove_digit(text) # 移除数字\n",
    "    text = traditional_to_simplified(text)  # 繁体字转简体字\n",
    "    text = re.sub(r\"[^\\u4e00-\\u9fa5]\", \"\", text)  # 只保留汉字字符\n",
    "    text = tokenize(text)\n",
    "    text = remove_stopwords(text)\n",
    "    return text\n",
    "\n",
    "df[\"content\"] = df[\"content\"].apply(process_row) # 作者在这里大概用了2分钟\n",
    "\n",
    "# 计算每条文本的长度\n",
    "sentence_lengths = df[\"content\"].apply(lambda x: len(x.split()))  # 计算每条文本的词数（已经分词）\n",
    "# 计算最大长度和平均长度\n",
    "max_length = sentence_lengths.max()\n",
    "avg_length = sentence_lengths.mean()\n",
    "print(f\"最大文本长度：{max_length}\")\n",
    "print(f\"平均文本长度：{avg_length:.2f}\")\n",
    "\n",
    "df.sample(5)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "90c0beb8-daab-4f56-bd8e-ca6391ad74d0",
   "metadata": {},
   "source": [
    "#### Word2Vec\n",
    "\n",
    "`Word2Vec训练很快，一分钟以内就能结束`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "4c737eff-6d74-4c26-9acb-fcdd69cb0364",
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "from gensim.models import Word2Vec\n",
    "\n",
    "def prepare_data(df, vector_size, max_length=100):\n",
    "    # 将文本转换为词列表\n",
    "    texts = df['content'].apply(lambda x: x.split())\n",
    "\n",
    "    # 首先创建一个空的词汇表并添加 <PAD> 词索引为 0\n",
    "    vocab = {\"<PAD>\": 0}\n",
    "    \n",
    "    # 训练Word2Vec模型\n",
    "    w2v_model = Word2Vec(sentences=texts, vector_size=vector_size, window=8, min_count=1, workers=4)\n",
    "    \n",
    "    # 获取模型训练后生成的词汇表\n",
    "    vocab.update({k: v+1 for k, v in w2v_model.wv.key_to_index.items()})\n",
    "    \n",
    "    # 将文本转换为序列，如果词不在词汇表中，则用0表示\n",
    "    sequences = [[vocab.get(word, 0) for word in text] for text in texts]\n",
    "\n",
    "    # 对每个序列进行填充或截断\n",
    "    padded = [s[:max_length] + [0] * (max_length - len(s)) if len(s) < max_length \n",
    "              else s[:max_length] for s in sequences]\n",
    "    \n",
    "    embedding_matrix = np.zeros((len(vocab), vector_size))\n",
    "    for word, i in vocab.items():\n",
    "        if word != \"<PAD>\":  # 确保 <PAD> 不会被赋予任何词向量\n",
    "            embedding_matrix[i] = w2v_model.wv[word]\n",
    "    \n",
    "    return np.array(padded), embedding_matrix, vocab\n",
    "\n",
    "vector_size=32\n",
    "padded, embedding_matrix, vocab = prepare_data(df, vector_size=vector_size)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "872a2c11-6a54-4485-89c9-006af96d0524",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "词汇表大小： 276419\n",
      "词汇表的一部分:\n",
      "词: <PAD>, 索引: 0\n",
      "词: 看, 索引: 1\n",
      "词: 人, 索引: 2\n",
      "词: 但, 索引: 3\n",
      "词: 好, 索引: 4\n",
      "狗 的词向量:\n",
      "[ 1.25383043 -2.4116931   0.8064031   1.5779922   2.63155127  1.46873689\n",
      " -0.07547206  0.4740181  -3.00884056 -0.86981738  5.24331665 -2.24276662\n",
      " -0.24413531 -1.14389253  0.38821632 -2.94821525 -0.94405043 -0.27858946\n",
      " -0.30593395  1.86716986  1.91396773  1.72029495  2.04792929  1.61745381\n",
      "  0.84995091  1.7602905  -0.46382093 -1.88935959 -2.54971528  3.30698657\n",
      " -0.37414455  2.08153915  1.61319864  2.43325162 -1.68176603  1.26123619\n",
      "  1.21501899 -0.10926893  3.18952775 -0.08478293  0.13994861 -1.54906392\n",
      "  1.66652811  0.08736216  1.62019384  1.28826094  1.43435764  0.80444884\n",
      "  3.76048446  1.97476625  2.87487316  0.35240531  2.00236297  0.7253406\n",
      " -1.14215207 -0.46701586  2.8651166   0.05218291  1.33643413  0.88709491\n",
      "  0.02159583  1.97483563 -3.71665955 -0.49163347]\n"
     ]
    }
   ],
   "source": [
    "# 查看词汇表的前几个词\n",
    "print(f'词汇表大小： {len(vocab)}')\n",
    "print(\"词汇表的一部分:\")\n",
    "for word, idx in list(vocab.items())[:5]:  # 查看前5个词\n",
    "    print(f\"词: {word}, 索引: {idx}\")\n",
    "\n",
    "# 查看嵌入矩阵中对应某个词的词向量\n",
    "word_to_check = '狗'  \n",
    "if word_to_check in vocab:\n",
    "    word_index = vocab[word_to_check]\n",
    "    word_vector = embedding_matrix[word_index]\n",
    "    print(f\"{word_to_check} 的词向量:\")\n",
    "    print(word_vector)\n",
    "else:\n",
    "    print(f\"词汇表中没有 {word_to_check} 这个词。\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a29ae4b5-f74a-4aae-a3fa-b3b6fcee0fe2",
   "metadata": {},
   "source": [
    "#### 构建数据集"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "d798fe2c-4a7b-40c6-853e-659d2fcc8106",
   "metadata": {},
   "outputs": [],
   "source": [
    "from torch.utils.data import Dataset, DataLoader\n",
    "from sklearn.model_selection import train_test_split\n",
    "\n",
    "class TextDataset(Dataset):\n",
    "    def __init__(self, sequences, labels):\n",
    "        self.sequences = torch.LongTensor(sequences)\n",
    "        self.labels = torch.LongTensor(labels)\n",
    "    \n",
    "    def __len__(self):\n",
    "        return len(self.labels)\n",
    "    \n",
    "    def __getitem__(self, idx):\n",
    "        return self.sequences[idx], self.labels[idx]\n",
    "\n",
    "X = padded\n",
    "y = df['label'].values\n",
    "# stratify=df[\"label\"] 使得训练集和测试集中的标签分布是均匀\n",
    "X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.1, random_state=42, stratify=df[\"label\"])  \n",
    "\n",
    "train_dataset = TextDataset(X_train, y_train)\n",
    "test_dataset = TextDataset(X_test, y_test)\n",
    "\n",
    "train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)\n",
    "test_loader = DataLoader(test_dataset, batch_size=32)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "71f5b357-af62-4af1-b467-f71fd1c5ed25",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "训练集大小: 457299\n",
      "测试集大小: 50811\n",
      "训练集标签分布: Counter({1: 228650, 0: 228649})\n",
      "测试集标签分布: Counter({0: 25406, 1: 25405})\n"
     ]
    }
   ],
   "source": [
    "# 查看训练集和测试集的大小\n",
    "print(f\"训练集大小: {len(train_dataset)}\")\n",
    "print(f\"测试集大小: {len(test_dataset)}\")\n",
    "\n",
    "# 查看训练集和测试集的标签分布\n",
    "from collections import Counter\n",
    "\n",
    "train_labels_counter = Counter(y_train)\n",
    "test_labels_counter = Counter(y_test)\n",
    "print(f\"训练集标签分布: {train_labels_counter}\")\n",
    "print(f\"测试集标签分布: {test_labels_counter}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c0d58254-08f2-43fc-a87e-23b4943cfafb",
   "metadata": {},
   "source": [
    "## 定义模型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "8559dadf-c087-4650-a68c-cee6efcfeef5",
   "metadata": {},
   "outputs": [],
   "source": [
    "import torch.nn as nn\n",
    "import torch.nn.functional as F\n",
    "\n",
    "class TextClassifier(nn.Module):\n",
    "    def __init__(self, vocab_size, embedding_dim, embedding_matrix, hidden_dim=64):\n",
    "        super().__init__()\n",
    "        # 定义词嵌入层，使用 embedding_matrix 初始化\n",
    "        self.embedding = nn.Embedding.from_pretrained(\n",
    "            torch.FloatTensor(embedding_matrix),\n",
    "            padding_idx=0\n",
    "        )\n",
    "        self.embedding.weight.requires_grad = False # True 确保嵌入层的参数可训练\n",
    "        \"\"\"\n",
    "        双向 LSTM 层：输入维度为 embedding_dim，输出维度为 hidden_dim。\n",
    "        batch_first=True : 输入张量的形状为 (batch_size, sequence_length)。\n",
    "        bidirectional=True : LSTM 会在两个方向上（正向和反向）处理输入序列，以捕捉更多上下文信息\n",
    "        (因为 LSTM 是双向的，它的输出将是两个隐藏层的连接, 所以实际输出维度为 hidden_dim * 2)\n",
    "        \"\"\"\n",
    "        self.lstm = nn.LSTM(\n",
    "            embedding_dim,    # 输入特征的维度\n",
    "            hidden_dim,       # 隐藏状态的维度\n",
    "            num_layers=2,     # LSTM的层数\n",
    "            batch_first=True, # 输入和输出的张量的第一个维度是batch_size\n",
    "            bidirectional=True, # 使用双向LSTM\n",
    "            dropout=0.5\n",
    "        )\n",
    "        self.fc1 = nn.Linear(hidden_dim * 2, hidden_dim)  # 添加一个额外的全连接层\n",
    "        self.fc2 = nn.Linear(hidden_dim, 2)  # 二分类任务\n",
    "        self.dropout = nn.Dropout(0.5)\n",
    "    \n",
    "    def forward(self, x):\n",
    "        embedded = self.embedding(x)\n",
    "        lstm_out, _ = self.lstm(embedded) # 第二个返回值_是LSTM的隐藏状态和单元状态；lstm_out形状： (batch_size, sequence_length, hidden_dim * 2)\n",
    "        last_hidden = lstm_out[:, -1, :] # 选择每个批次中的最后一个时刻的输出，形状为 (batch_size, hidden_dim * 2)\n",
    "        dropped = self.dropout(last_hidden)\n",
    "        fc1_out = F.relu(self.fc1(dropped))\n",
    "        fc_out = self.fc2(fc1_out)\n",
    "        return fc_out\n",
    "\n",
    "\n",
    "model = TextClassifier(len(vocab) + 1, vector_size, embedding_matrix).to(device)\n",
    "loss_fn = nn.CrossEntropyLoss()\n",
    "optimizer = torch.optim.Adam(model.parameters(), lr=1e-3)\n",
    "\n",
    "# 初始化学习率调度器，每step_size个epoch将学习率衰减为原来的gamma倍\n",
    "scheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=2, gamma=0.5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "c7c7826e-5f40-474f-a02a-1d412d87c6ff",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "TextClassifier(\n",
      "  (embedding): Embedding(276419, 64, padding_idx=0)\n",
      "  (lstm): LSTM(64, 64, num_layers=2, batch_first=True, dropout=0.5, bidirectional=True)\n",
      "  (fc1): Linear(in_features=128, out_features=64, bias=True)\n",
      "  (fc2): Linear(in_features=64, out_features=2, bias=True)\n",
      "  (dropout): Dropout(p=0.5, inplace=False)\n",
      ")\n",
      "模型总参数数量: 17,865,090\n",
      "模型可训练参数数量: 174,274\n"
     ]
    }
   ],
   "source": [
    "# 查看模型结构\n",
    "# 打印模型参数总数和可训练参数总数\n",
    "def count_parameters(model):\n",
    "    total_params = sum(p.numel() for p in model.parameters())  # 所有参数数量\n",
    "    trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)  # 需要训练的参数数量\n",
    "    print(f\"模型总参数数量: {total_params:,}\")\n",
    "    print(f\"模型可训练参数数量: {trainable_params:,}\")\n",
    "\n",
    "print(model)\n",
    "count_parameters(model)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "66a0e293-831e-4ace-8ab3-981be5be48f8",
   "metadata": {},
   "source": [
    "## 模型训练与评估"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "fdbfde3d-bcc5-4bbc-b954-d3e576d1cb90",
   "metadata": {},
   "outputs": [],
   "source": [
    "from tqdm import tqdm\n",
    "\n",
    "# 训练函数\n",
    "def train(dataloader, model, loss_fn, optimizer):\n",
    "    model.train()  # 设置模型为训练模式\n",
    "    \n",
    "    running_loss = 0.0\n",
    "    correct = 0\n",
    "    total = 0\n",
    "\n",
    "    # 使用 tqdm 包裹数据加载器，显示进度条\n",
    "    progress_bar = tqdm(dataloader, desc=\"Training\", leave=False)\n",
    "    for texts, labels in progress_bar:\n",
    "        # 将数据移动到设备\n",
    "        texts, labels = texts.to(device), labels.to(device)\n",
    "\n",
    "        # 前向传播\n",
    "        outputs = model(texts)\n",
    "        loss = loss_fn(outputs, labels)\n",
    "\n",
    "        # 反向传播和优化\n",
    "        optimizer.zero_grad()\n",
    "        loss.backward()\n",
    "        optimizer.step()  # 更新模型参数\n",
    "\n",
    "        # 统计指标\n",
    "        running_loss += loss.item()\n",
    "        _, predicted = torch.max(outputs, 1)\n",
    "        total += labels.size(0)\n",
    "        correct += (predicted == labels).sum().item()\n",
    "\n",
    "        # 更新进度条描述\n",
    "        progress_bar.set_postfix(lr=optimizer.param_groups[0]['lr'], loss=loss.item())\n",
    "        \n",
    "    scheduler.step()  # 更新学习率       \n",
    "\n",
    "    accuracy = 100 * correct / total\n",
    "    avg_loss = running_loss / len(dataloader)\n",
    "    return avg_loss, accuracy"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "36267fd1-6b5e-4a5e-b9a7-e97652a9948c",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 测试函数\n",
    "def evaluate(dataloader, model, loss_fn):\n",
    "    model.eval()  # 设置模型为评估模式\n",
    "    running_loss = 0.0\n",
    "    correct = 0\n",
    "    total = 0\n",
    "\n",
    "    with torch.no_grad():  # 关闭梯度计算\n",
    "        progress_bar = tqdm(dataloader, desc=\"Evaluating\", leave=False)\n",
    "        for texts, labels in progress_bar:\n",
    "            # 将数据移动到设备\n",
    "            texts, labels = texts.to(device), labels.to(device)\n",
    "\n",
    "            # 前向传播\n",
    "            outputs = model(texts)\n",
    "            loss = loss_fn(outputs, labels)\n",
    "\n",
    "            # 统计指标\n",
    "            running_loss += loss.item()\n",
    "            _, predicted = torch.max(outputs, 1)\n",
    "            total += labels.size(0)\n",
    "            correct += (predicted == labels).sum().item()\n",
    "            # 更新进度条描述\n",
    "            progress_bar.set_postfix(loss=loss.item())\n",
    "\n",
    "    accuracy = 100 * correct / total\n",
    "    avg_loss = running_loss / len(dataloader)\n",
    "    return avg_loss, accuracy"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "59d90b49-560f-40b2-a1cd-d2fe798c8910",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 1/10\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "                                                                                                                       \r"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch: 1, Train_acc:56.4%, Train_loss:0.669, Test_acc:66.4%，Test_loss:0.607\n",
      "Epoch 2/10\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "                                                                                                                       \r"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch: 2, Train_acc:66.4%, Train_loss:0.603, Test_acc:67.8%，Test_loss:0.584\n",
      "Epoch 3/10\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "                                                                                                                       \r"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch: 3, Train_acc:68.0%, Train_loss:0.585, Test_acc:68.3%，Test_loss:0.579\n",
      "Epoch 4/10\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "                                                                                                                       \r"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch: 4, Train_acc:68.4%, Train_loss:0.578, Test_acc:68.7%，Test_loss:0.576\n",
      "Epoch 5/10\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "                                                                                                                       \r"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch: 5, Train_acc:69.1%, Train_loss:0.570, Test_acc:68.8%，Test_loss:0.576\n",
      "Epoch 6/10\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "                                                                                                                       \r"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch: 6, Train_acc:69.4%, Train_loss:0.566, Test_acc:69.0%，Test_loss:0.574\n",
      "Epoch 7/10\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "                                                                                                                       \r"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch: 7, Train_acc:69.7%, Train_loss:0.562, Test_acc:68.9%，Test_loss:0.574\n",
      "Epoch 8/10\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "                                                                                                                       \r"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch: 8, Train_acc:69.8%, Train_loss:0.559, Test_acc:69.1%，Test_loss:0.575\n",
      "Epoch 9/10\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "                                                                                                                       \r"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch: 9, Train_acc:70.0%, Train_loss:0.557, Test_acc:69.1%，Test_loss:0.573\n",
      "Epoch 10/10\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "                                                                                                                       "
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch:10, Train_acc:70.1%, Train_loss:0.556, Test_acc:69.2%，Test_loss:0.574\n",
      "训练完成!\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\r"
     ]
    }
   ],
   "source": [
    "# 开始训练\n",
    "\n",
    "num_epochs = 10\n",
    "\n",
    "train_loss = []\n",
    "train_acc  = []\n",
    "test_loss  = []\n",
    "test_acc   = []\n",
    "\n",
    "for epoch in range(num_epochs):\n",
    "    print(f\"Epoch {epoch+1}/{num_epochs}\")\n",
    "    \n",
    "    epoch_train_loss, epoch_train_acc = train(train_loader, model, loss_fn, optimizer)\n",
    "\n",
    "    # 在测试集上评估\n",
    "    epoch_test_loss, epoch_test_acc = evaluate(test_loader, model, loss_fn)\n",
    "\n",
    "    train_acc.append(epoch_train_acc)\n",
    "    train_loss.append(epoch_train_loss)\n",
    "    test_acc.append(epoch_test_acc)\n",
    "    test_loss.append(epoch_test_loss)\n",
    "    # 打印训练和测试结果\n",
    "    template = ('Epoch:{:2d}, Train_acc:{:.1f}%, Train_loss:{:.3f}, Test_acc:{:.1f}%，Test_loss:{:.3f}')\n",
    "    print(template.format(epoch+1, epoch_train_acc, epoch_train_loss, epoch_test_acc, epoch_test_loss))\n",
    "\n",
    "print(\"训练完成!\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "dcb37d44-4e75-4a91-9041-2ffe8f030b7e",
   "metadata": {},
   "source": [
    "## 结果可视化"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "21e1b89f-7b7f-4903-bddb-500fe3f39514",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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Gnd7KywlIRaixurT1Ic5W//j4LlEYlOy8HayNndIQghx0woSxgI6nY53332XdevWcfnyZbKzs8nOzsbOzq7M4zRp0sT4uKDbeFxcXLn3KZg0Oi4ujsDAQE6dOmVMygu0bt2aX3/9tVzXVdTZs2fJzc2lffv2xjKNRkPr1q05efIkAM899xyPPvoof/75J927d6dfv360a9cOgOHDh9OtWzfq1avHAw88QO/evenevftNxVJekkQLISpMr1dIzMgplBBnGrtaxxZKkDPKOemWnZU6PyG2MWlF9jEmzTa42GoqrXuUEKJ68nexpUWQC0cuJPHj39E807GWuUMSQpiBjUbNibd7mO3claVocjx//nwWLlzIokWLaNy4MXZ2dowbN46cnLJ77BWdkEylUqHXlz0vTOF9Cu6/Cu9T0rLGN6tg37KWSu7ZsycXLlzgp59+YseOHdx///08//zzzJs3j+bNm3Pu3Dm2bNnCjh07GDBgAF27duW777676ZhuRJJoIYSRXq+QkJ7DldQsrl7LJu5aFnGp2cQVPL6WTVxqNlevZZOjK9+kXC62mkIJsU0JrcjWOFiXfykGIYQoy0Phvhy5kMQPxySJFqKmUqlUldaluirZu3cvDz30EEOGDAEMSe3p06cJCwu7o3HUq1ePQ4cOMXToUGPZH3/8cdPHq1OnDlZWVvz222/GCalzc3P5448/GDdunLGeh4cHw4cPZ/jw4XTs2JFXXnmFefPmAeDo6MjAgQMZOHAgjz32GA888ACJiYkVnq28vKrfX5cQophcnZ74tGxjQnwl1ZAQXy2SJMen5ZR7ci6VCjzstUVajW2KtSLLjNNCmN+SJUt47733iImJoWHDhixatIiOHTuWWj87O5u3336br776itjYWPz9/Zk6darJpKLJyclMnTqVDRs2kJSUREhICPPnz6dXr1534pJK1auxD9N/OMGxSymcj08n2L3sbo5CCHG3qFOnDuvXr2ffvn24uLiwYMECYmNj73gS/eKLLzJy5EhatmxJu3btWLduHX///Te1at34i8vCy3gVaNCgAc899xyvvPIKrq6uBAYGMnfuXDIyMnj66acBw7jrFi1a0LBhQ7Kzs/nxxx+N171w4UJ8fHwIDw/HwsKCb7/9Fm9vb5ydnSv1uguTJFqIu1hWrq7kFuPUbK5cyyYuv0U5MSOH8vayUanA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oOtg4X2KdidUFIWyJCYm8v3335Obm8vSpUuN5TqdjhUrVjBnzpxik6kVdaPXLSwsisWRm1v85rLo+/rNN98wfvx45s+fT9u2bXFwcOC9997j4MGD5TovwJNPPslrr73G/v372b9/P8HBwXTs2PGG+wkhRFnUFio6hLrTIdSdGf3y2HI8lg1/GpbLOngukYPnEnlz03F65C+X1aGOO2qLqtktVQhRcRVqiZ42bRoqlcpkKzwJT1paGi+88AL+/v7Y2NgQFhZmclNW1eyJMMw62Kmux90/jkWIu4BKpcLWytIs2+38N753714eeughhgwZQtOmTalVqxanT5++becrTb169Th06JBJ2R9//FHmPqtXr8bf359jx45x9OhR47Zo0SI+//xz8vLyaNKkCZcuXSIiIqLEYzRp0oRffvml1HN4eHiYzHqemprKuXPnbng9e/fupV27dowZM4ZmzZpRp04dzp49a3zdwcGB4ODgMs/t5uZGv379WLlyJStXrjR2URdCiMpil79c1tcj7+G3SffxSo961PKwIytXz/+ORjNsxSHazv6F2ZtPcir2mrnDFUJUggq3RDds2JAdO3YYnxdMLAMwfvx4du7cyVdffUVwcDDbtm1jzJgx+Pr68tBDD1VOxJVIxkMLISpDnTp1WL9+Pfv27cPFxYUFCxYQGxtLWFjYHY3jxRdfZOTIkbRs2ZJ27dqxbt06/v77b5Pxy0UtX76cxx57jEaNGpmUBwUFMWnSJH766SceeughOnXqxKOPPsqCBQuoU6cO//33HyqVigceeIDJkyfTuHFjxowZw+jRo7GysmLnzp30798fd3d37rvvPlatWkWfPn1wcXHhjTfeMPnsKE2dOnX44osv+PnnnwkJCeHLL7/k8OHDJhOlTZs2jdGjR+Pp6Wmc/Oz333/nxRdfNNZ55pln6N27NzqdjmHDht3EOyuEEOXj52xjXC7r2KUUNvx5iU3Hoom7ls0neyL5ZE8kHg5a6njYU8fTnlAve+NjDwetNOoIcZeocBJtaWlZ6tql+/fvZ9iwYXTp0gWAUaNG8cknn/DHH39UuSQ6OjmTM3FpWKigfW0ZDy2EuHlvvPEG586do0ePHtja2jJq1Cj69etHSkrKHY1j8ODBREZGMnHiRLKyshgwYADDhw8v1jpd4MiRIxw7doxPP/202GsODg50796d5cuX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",
      "text/plain": [
       "<Figure size 1200x300 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "\n",
    "epochs_range = range(num_epochs)\n",
    "\n",
    "plt.figure(figsize=(12, 3))\n",
    "plt.subplot(1, 2, 1)\n",
    "\n",
    "plt.plot(epochs_range, train_acc, label='Training Accuracy')\n",
    "plt.plot(epochs_range, test_acc, label='Test Accuracy')\n",
    "plt.legend(loc='lower right')\n",
    "plt.title('Training and Validation Accuracy')\n",
    "\n",
    "plt.subplot(1, 2, 2)\n",
    "plt.plot(epochs_range, train_loss, label='Training Loss')\n",
    "plt.plot(epochs_range, test_loss, label='Test Loss')\n",
    "plt.legend(loc='upper right')\n",
    "plt.title('Training and Validation Loss')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b0cea89f-dce5-4e40-9bf4-649809b33d96",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.20"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
